package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
	"time"

	"gitee.com/fcsvr/fc/fclog"
	"github.com/tidwall/gjson"
)

func GetOperatorToFile() {
	filePath := "basedata/operator"
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()
	writer := bufio.NewWriter(file)

	url := "https://api.worldquantbrain.com/operators"
	resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
	strBody := string(resp.Body())

	result := gjson.Parse(strBody)

	// 获取数组长度
	arrayLength := len(result.Array())
	for i := 0; i < arrayLength; i++ {
		index_name := strconv.Itoa(i) + ".name"
		index_def := strconv.Itoa(i) + ".definition"
		operator := gjson.Get(strBody, index_name).String() + ":" + gjson.Get(strBody, index_def).String() + "\n"
		fclog.Info(operator)
		if _, err := writer.WriteString(operator); err != nil {
			log.Fatal(err)
		}
	}

	writer.Flush()
	//fmt.Println("operator len = ", arrayLength)
	fclog.Info("%d", len(result.Array()))
}

func GetDataField(dataset string, instrument string, region string, delay string, universe string, typ string) []string {
	fields := make([]string, 0, 0)
	baseurl := "https://api.worldquantbrain.com/data-fields?&instrumentType="
	baseurl += instrument
	baseurl += "&region="
	baseurl += region
	baseurl += "&delay="
	baseurl += delay
	baseurl += "&universe="
	baseurl += universe
	baseurl += "&dataset.id="
	baseurl += dataset
	baseurl += "&limit=50&offset="
	//baseurl := "https://api.worldquantbrain.com/data-fields?" +
	//"&instrumentType=EQUITY&region=USA&delay=1&universe=TOP3000&dataset.id=fundamental6&limit=50&offset="
	url := baseurl + "0"
	fclog.Debug(url)
	resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
	strBody := string(resp.Body())
	count := gjson.Get(strBody, "count").Int()
	fclog.Info("all count = %d", count)
	for i := 50; i < int(count+50); i += 50 {
		for j := 0; j < 50; j++ {
			index := "results." + strconv.Itoa(j)
			if !gjson.Get(strBody, index).Exists() {
				break
			}
			index_id := index + ".id"
			index_typ := index + ".type"

			field_id := gjson.Get(strBody, index_id)
			field_typ := gjson.Get(strBody, index_typ)
			//fmt.Println(field_id.String(), field_typ.String())
			//fmt.Println(field_id.String(), typ)
			if field_typ.String() == typ {
				fields = append(fields, field_id.String())
			}
		}
		url = baseurl + strconv.Itoa(i)
		resp, _ = G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody = string(resp.Body())
	}
	fclog.Info("fields len = %d", len(fields))
	fclog.Info("%v", fields)
	return fields
}
func GetDataFieldToFile(datasets []string, instrument string, region string, delay string, universe string, typ string) {
	for _, dataset := range datasets {

		filePath := "data/" + region + "-" + universe + "-" + dataset + "-" + typ
		file, _ := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
		defer file.Close()
		writer := bufio.NewWriter(file)

		baseurl := "https://api.worldquantbrain.com/data-fields?&instrumentType="
		baseurl += instrument
		baseurl += "&region="
		baseurl += region
		baseurl += "&delay="
		baseurl += delay
		baseurl += "&universe="
		baseurl += universe
		baseurl += "&dataset.id="
		baseurl += dataset
		baseurl += "&limit=50&offset="
		//baseurl := "https://api.worldquantbrain.com/data-fields?" +
		//"&instrumentType=EQUITY&region=USA&delay=1&universe=TOP3000&dataset.id=fundamental6&limit=50&offset="
		url := baseurl + "0"
		resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody := string(resp.Body())
		count := gjson.Get(strBody, "count").Int()
		fclog.Info("all count = %d", count)
		for i := 50; i < int(count+50); i += 50 {
			for j := 0; j < 50; j++ {
				index := "results." + strconv.Itoa(j)
				if !gjson.Get(strBody, index).Exists() {
					break
				}
				index_id := index + ".id"
				index_typ := index + ".type"
				//index_desc := index + ".description"

				field_id := gjson.Get(strBody, index_id)
				field_typ := gjson.Get(strBody, index_typ)
				//field_desc := gjson.Get(strBody, index_desc)
				//fmt.Println(field_id.String(), field_typ.String())
				//fmt.Println(field_id.String(), typ)
				if field_typ.String() == typ {
					//field := field_id.String() + ":" + field_desc.String() + "\n"
					field := field_id.String() + "\n"
					writer.WriteString(field)
				}
			}
			url = baseurl + strconv.Itoa(i)
			resp, _ = G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
			strBody = string(resp.Body())
		}
		writer.Flush()
	}
}

func GetImproveAlphas(startdate string, enddate string, fitness float32, sharpe float32, region string) {
	filePath := "file/" + "improve-" + startdate
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
	if err != nil {
		fclog.Error("GetImproveAlphas openFile err = %v", err)
		return
	}
	defer file.Close()
	writer := bufio.NewWriter(file)

	alphas := make(map[string]bool)
	offset := 0
	baseurl := "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d&status=UNSUBMITTED%%1FIS_FAIL&dateCreated%%3E%sT00:00:00-04:00&dateCreated%%3C%sT00:00:00-04:00&is.fitness%%3E%f&is.sharpe%%3E%f&settings.region=%s&order=-is.sharpe&hidden=false&type!=SUPER"
	url := fmt.Sprintf(baseurl, offset, startdate, enddate, fitness, sharpe, region)
	fmt.Println(url)

	resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
	strBody := string(resp.Body())
	count := gjson.Get(strBody, "count").Int()
	fclog.Info("Alpha positive count = %d", count)
	for i := 0; i < int(count); i += 100 {
		url = fmt.Sprintf(baseurl, i, startdate, enddate, fitness, sharpe, region)
		resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody := string(resp.Body())
		for j := 0; j < 100; j++ {
			index := "results." + strconv.Itoa(j)
			if !gjson.Get(strBody, index).Exists() {
				break
			}
			index_code := index + ".regular.code"
			alpha := gjson.Get(strBody, index_code).String()
			alpha = strings.ReplaceAll(alpha, "\r\n", "")
			alpha = strings.ReplaceAll(alpha, " ", "")
			for _, v := range G_Decay {
				for _, v1 := range G_Neutra[region] {
					alpha_decay := "@" + alpha + "@" + strconv.Itoa(v) + "@" + v1 + "@" + region + "@" + G_Universe[region][0]
					alphas[alpha_decay] = true
				}
			}
			//fclog.Debug("%d, %d", f, len(alphas))
			//fmt.Printf("%s\n", alpha)
		}

	}
	fitness = 1.5
	sharpe = 1.5
	offset = 0
	baseurl = "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d&status=UNSUBMITTED%%1FIS_FAIL&dateCreated%%3E%sT00:00:00-04:00&dateCreated%%3C%sT00:00:00-04:00&is.fitness%%3C-%f&is.sharpe%%3C-%f&settings.region=%s&order=-is.sharpe&hidden=false&type!=SUPER"
	url = fmt.Sprintf(baseurl, offset, startdate, enddate, fitness, sharpe, region)
	//fmt.Println(url)

	resp, _ = G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
	strBody = string(resp.Body())
	count = gjson.Get(strBody, "count").Int()
	fclog.Info("Alpha negative count = %d", count)
	for i := 0; i < int(count); i += 100 {
		url = fmt.Sprintf(baseurl, i, startdate, enddate, fitness, sharpe, region)
		resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody := string(resp.Body())
		for j := 0; j < 100; j++ {
			index := "results." + strconv.Itoa(j)
			if !gjson.Get(strBody, index).Exists() {
				break
			}
			index_code := index + ".regular.code"
			alpha := "-" + gjson.Get(strBody, index_code).String()
			alpha = strings.ReplaceAll(alpha, "\r\n", "")
			alpha = strings.ReplaceAll(alpha, " ", "")
			for _, v := range G_Decay {
				for _, v1 := range G_Neutra[region] {
					alpha_decay := "@" + alpha + "@" + strconv.Itoa(v) + "@" + v1 + "@" + region + "@" + G_Universe[region][0]
					alphas[alpha_decay] = true
				}
			}
			//fclog.Debug("%d, %d", f, len(alphas))
			//fmt.Printf("%s\n", alpha)
		}
	}

	fclog.Debug("Improve alpha len = %d", len(alphas))
	for k, _ := range alphas {
		writer.WriteString(k + "\n")
	}
	writer.Flush()
}

func GetImproveAlphas_AddGroupOp(startdate string, enddate string, region string) {
	filePath := "file/" + "improve-" + startdate
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
	if err != nil {
		fclog.Error("GetImproveAlphas openFile err = %v", err)
		return
	}
	defer file.Close()
	writer := bufio.NewWriter(file)

	alphas := make(map[string]bool)
	offset := 0
	baseurl := "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d&status=UNSUBMITTED%%1FIS_FAIL&dateCreated%%3E%sT00:00:00-04:00&dateCreated%%3C%sT00:00:00-04:00&color=BLUE&settings.region=%s&order=-is.sharpe&hidden=false&type!=SUPER"
	url := fmt.Sprintf(baseurl, offset, startdate, enddate, region)
	fmt.Println(url)

	resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
	strBody := string(resp.Body())
	count := gjson.Get(strBody, "count").Int()
	fclog.Info("Alpha positive count = %d", count)
	for i := 0; i < int(count); i += 100 {
		url = fmt.Sprintf(baseurl, i, startdate, enddate, region)
		resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody := string(resp.Body())
		for j := 0; j < 100; j++ {
			index := "results." + strconv.Itoa(j)
			if !gjson.Get(strBody, index).Exists() {
				break
			}
			index_code := index + ".regular.code"
			alpha := gjson.Get(strBody, index_code).String()
			alpha = strings.ReplaceAll(alpha, "\r\n", "")
			alpha = strings.ReplaceAll(alpha, " ", "")
			alpha = strings.ReplaceAll(alpha, ";", "")
			for _, groupOp := range G_GroupOp {
				alpha1 := groupOp + "(" + alpha + ", industry)"
				//for _, v := range G_Decay {
				for _, v1 := range G_Neutra[region] {
					//alpha_decay := "@" + alpha1 + " @4" + " @INDUSTRY" + " @" + region + " @" + "TOP3000"
					alpha_decay := "@" + alpha1 + " @4" + " @" + v1 + " @" + region + " @" + "TOP3000"
					alphas[alpha_decay] = true
				}
				//}
			}
			//fclog.Debug("%d, %d", f, len(alphas))
			//fmt.Printf("%s\n", alpha)
		}

	}

	fclog.Debug("Improve alpha len = %d", len(alphas))
	for k, _ := range alphas {
		writer.WriteString(k + "\n")
	}
	writer.Flush()
}

func GetImproveBlueAlphas(region string) {
	filePath := "file/" + "improve-blue"
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
	if err != nil {
		fclog.Error("GetImproveAlphas openFile err = %v", err)
		return
	}
	defer file.Close()
	writer := bufio.NewWriter(file)

	alphas := make(map[string]bool)
	offset := 0
	baseurl := "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d&color=BLUE&settings.region=%s&order=is.sharpe&hidden=false&type!=SUPER"
	url := fmt.Sprintf(baseurl, offset, region)
	//fmt.Println(url)

	resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
	strBody := string(resp.Body())
	count := gjson.Get(strBody, "count").Int()
	fclog.Info("Alpha positive count = %d", count)
	for i := 0; i < int(count); i += 100 {
		url = fmt.Sprintf(baseurl, i, region)
		resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody := string(resp.Body())
		for j := 0; j < 100; j++ {
			index := "results." + strconv.Itoa(j)
			if !gjson.Get(strBody, index).Exists() {
				break
			}
			index_code := index + ".regular.code"
			alpha := gjson.Get(strBody, index_code).String()
			alpha = strings.ReplaceAll(alpha, "\r\n", "")
			alpha = strings.ReplaceAll(alpha, " ", "")
			alpha = "alpha=" + alpha + ";"
			index_decay := index + ".settings.decay"
			decay := gjson.Get(strBody, index_decay).Int()
			for _, v := range G_TradeWhen {
				alpha_1 := alpha + v
				alpha_decay := "@ " + alpha_1 + " @" + strconv.Itoa(int(decay))
				alphas[alpha_decay] = true
			}
			//fmt.Printf("%s\n", alpha)
		}
	}

	for k, _ := range alphas {
		writer.WriteString(k + "\n")
	}
	writer.Flush()
}

func RefreshAlphaByColor(region string, color string) {
	fclog.Info("RefreshAlphaByColor")
	alphas := make(map[string]bool)
	offset := 0
	baseurl := "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d&color=%s&settings.region=%s&order=is.sharpe&hidden=false&type!=SUPER"
	url := fmt.Sprintf(baseurl, offset, color, region)
	fmt.Println(url)

	resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
	strBody := string(resp.Body())
	count := gjson.Get(strBody, "count").Int()
	fclog.Info("Alpha %s count = %d", color, count)
	for i := 0; i < int(count); i += 100 {
		url = fmt.Sprintf(baseurl, i, color, region)
		resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody := string(resp.Body())
		for j := 0; j < 100; j++ {
			index := "results." + strconv.Itoa(j)
			if !gjson.Get(strBody, index).Exists() {
				break
			}
			index_id := index + ".id"
			alpha := gjson.Get(strBody, index_id).String()
			alphas[alpha] = true
		}
	}

	i := 0
	for k, _ := range alphas {
		i++
		/*
			if i < 306 {
				continue
			}
		*/
		time.Sleep(4 * time.Second)
		CheckAlpha(i, k)
	}
}

func GetAlphaPnl(alphaid string) *AlphaPnl {
	url := "https://api.worldquantbrain.com/alphas/" + alphaid + "/recordsets/pnl"
	recordsLen := 0
	alphaPnl := &AlphaPnl{}
	cn := 1
	for recordsLen == 0 {
		resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody := string(resp.Body())
		recordsLen = int(gjson.Get(strBody, "records.#").Int())
		if recordsLen > 0 {
			fclog.Info("GetAlphaPnl alphaid = %s, code = %d, len = %d", alphaid, resp.StatusCode(), recordsLen)
		}

		alphaPnl.Alphaid = alphaid
		alphaPnl.Vals = make([]PnlVal, recordsLen, recordsLen)
		for i := 0; i < recordsLen; i++ {
			indexDate := "records." + strconv.Itoa(i) + ".0"
			indexVal := "records." + strconv.Itoa(i) + ".1"
			alphaPnl.Vals[i].Date = gjson.Get(strBody, indexDate).String()
			alphaPnl.Vals[i].Val = gjson.Get(strBody, indexVal).Float()
		}
		time.Sleep(time.Duration(cn) * time.Second)
		cn++
	}
	return alphaPnl
}

func GetActiveAlphas(region string) map[string]bool {
	filePath := "file/" + "active"
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
	if err != nil {
		fclog.Error("GetActiveAlphas OpenFile = %v", err)
	}
	defer file.Close()
	writer := bufio.NewWriter(file)

	alphas := make(map[string]bool)
	offset := 0
	baseurl := "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d&status=ACTIVE%%1FIS_FAIL&settings.region=%s&order=-is.sharpe&hidden=false&type!=SUPER"
	url := fmt.Sprintf(baseurl, offset, region)
	//fmt.Println(url)

	resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
	strBody := string(resp.Body())
	count := gjson.Get(strBody, "count").Int()
	fclog.Info("Active alpha count = %d", count)
	for i := 0; i < int(count); i += 100 {
		url = fmt.Sprintf(baseurl, i, region)
		resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody := string(resp.Body())
		for j := 0; j < 100; j++ {
			index := "results." + strconv.Itoa(j)
			if !gjson.Get(strBody, index).Exists() {
				break
			}
			index_code := index + ".regular.code"
			alpha := gjson.Get(strBody, index_code).String()
			alpha = strings.ReplaceAll(alpha, "\r\n", "")
			//fmt.Printf("%s\n", alpha)
			alphas[alpha] = true
		}
	}

	for k, _ := range alphas {
		writer.WriteString(k + "\n")
	}
	writer.Flush()
	return alphas
}

func GetActiveAlphaPnl() {
	fclog.Info("GetActiveAlphaPnl")
	filePath := "file/" + "pnl"
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
	if err != nil {
		fclog.Error("GetActiveAlphaPnl OpenFile = %v", err)
	}
	defer file.Close()
	writer := bufio.NewWriter(file)

	alphaIDs := make(map[string]float64)
	offset := 0

	//baseurl := "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d&status=ACTIVE&settings.region=%s&order=-is.sharpe&hidden=false&type!=SUPER"
	baseurl := "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d&status=ACTIVE&order=-is.sharpe&hidden=false&type!=SUPER"
	url := fmt.Sprintf(baseurl, offset)
	fclog.Debug(url)

	resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
	strBody := string(resp.Body())
	count := gjson.Get(strBody, "count").Int()
	fclog.Info("Active alpha code = %d, count = %d", resp.StatusCode(), count)
	for i := 0; i < int(count); i += 100 {
		url = fmt.Sprintf(baseurl, i)
		resp, _ := G_Client.R().SetHeader("Content-Type", "application/json").Get(url)
		strBody := string(resp.Body())
		for j := 0; j < 100; j++ {
			index := "results." + strconv.Itoa(j)
			if !gjson.Get(strBody, index).Exists() {
				break
			}
			index_tag := index + ".is.tags.#"
			tagsLen := gjson.Get(strBody, index_tag).Int()
			if tagsLen == 0 {
				continue
			}
			index_code := index + ".id"
			alphaid := gjson.Get(strBody, index_code).String()
			alphaid = strings.ReplaceAll(alphaid, "\r\n", "")

			index_sharpe := index + ".is.sharpe"
			alphasharpe := gjson.Get(strBody, index_sharpe).Float()
			//fmt.Printf("%s\n", alphaid)
			alphaIDs[alphaid] = alphasharpe
		}
	}

	fclog.Info("GetActiveAlphaPnl online pnl len = %d", len(alphaIDs))
	for k, v := range alphaIDs {
		if _, exists := G_ActiveAlpha[k]; !exists {
			pnl := GetAlphaPnl(k)
			pnl.Sharpe = v
			G_ActiveAlphaPnl.AlphaPnls = append(G_ActiveAlphaPnl.AlphaPnls, pnl)
			G_ActiveAlpha[k] = true
			fclog.Info("GetActiveAlphaPnl add = %s", k)
		}
	}
	fclog.Info("GetActiveAlphaPnl file pnl len = %d", len(G_ActiveAlphaPnl.AlphaPnls))

	activeAlphaPnlBytes, _ := json.Marshal(G_ActiveAlphaPnl)

	writer.Write(activeAlphaPnlBytes)
	writer.Flush()
}

func GetActiveAlphaPnlFromFile() {
	pnlJson, err := os.ReadFile(G_PnlFile)
	if err != nil {
		fclog.Error("GetAlphaPnlFromFile err = %v", err)
		return
	}

	G_ActiveAlphaPnl.AlphaPnls = make([]*AlphaPnl, 0)
	err = json.Unmarshal(pnlJson, &G_ActiveAlphaPnl)
	if err != nil {
		fclog.Error("GetAlphaPnlFromFile unmarshal err = %v", err)
		return
	}
	for _, v := range G_ActiveAlphaPnl.AlphaPnls {
		G_ActiveAlpha[v.Alphaid] = true
		//fclog.Debug("%s", v.Alphaid)
	}
	fclog.Info("GetAlphaPnlFromFile len = %d", len(G_ActiveAlphaPnl.AlphaPnls))
}
